﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Yuans.BinaryConfig.Utils
{
    public class HashMethod
    {
        // Orignal from http://www.azillionmonkeys.com/qed/hash.html
        public static UInt32 SuperFastHash(byte[] data)
        {
            int len = data.Length;
            UInt32 hash = (UInt32)len;
            UInt32 tmp;
            int rem;
            int dataBytePtr = 0;

            if (data == null) return 0;

            rem = len & 3;
            len >>= 2;

            /* Main loop */
            for (; len > 0; len--)
            {
                hash += BitConverter.ToUInt16(data, dataBytePtr);
                tmp = ((UInt32)BitConverter.ToUInt16(data, (dataBytePtr + 2)) << 11) ^ hash;
                hash = (hash << 16) ^ tmp;
                dataBytePtr += 2 * sizeof(UInt16);
                hash += hash >> 11;
            }

            /* Handle end cases */
            switch (rem)
            {
                case 3: hash += BitConverter.ToUInt16(data, dataBytePtr);
                    hash ^= hash << 16;
                    hash ^= (UInt32)(((sbyte)data[sizeof(UInt16) + dataBytePtr]) << 18);
                    hash += hash >> 11;
                    break;
                case 2: hash += BitConverter.ToUInt16(data, dataBytePtr);
                    hash ^= hash << 11;
                    hash += hash >> 17;
                    break;
                case 1: hash += (UInt32)((sbyte)data[dataBytePtr]);
                    hash ^= hash << 10;
                    hash += hash >> 1;
                    break;
            }

            /* Force "avalanching" of final 127 bits */
            hash ^= hash << 3;
            hash += hash >> 5;
            hash ^= hash << 4;
            hash += hash >> 17;
            hash ^= hash << 25;
            hash += hash >> 6;

            return hash;
        }
    }
}
